
package DB;

import Data.*;

import java.sql.PreparedStatement;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import java.util.Date;
import java.sql.Timestamp;

/**
 * Mapper Klasse, die Booking Objekte auf eine relationale DB abbildet.
 * Diese Klasse erlaubt zahlreiche Operationen, um eine Bokking zu verwalten, z.B. eine LöschOperation oder eine EinfügeOperation
 * @author Stefan Fellner
 */
public class BookingMapper {

    /*
     * Um sicher zu stellen, dass nur eine Instanz von der Klasse erzeugt wird, wird die Singleton Pattern angewendet.
     * Durch das Schlüsselwort static wird dies erreicht.
     * Quelle: http://www.theserverside.de/singleton-pattern-in-java/
     */
    private static BookingMapper bookingMapper = null;

    private ConnectionManager manager;

    //mittels protected wird sichergestellt, dass mit new keine neuen Instanzen erstellt werden können. Sobals ein Mapper Objekt erstellt wird, wird eine connection aufgebaut
    protected BookingMapper(){
        manager = ConnectionManager.getInstance();

    }

    /* Eine Instanz dieser Klasse sollte immer mittels der folgenden Methode erstellt werden.
     * Dadurch wird sicher gestellt, dass nur eine Instanz von dieser Klasse vorhanden ist.
     * @return DAS <code>BokkingMapper</code> Objekt
     * @see bookingMapper
     */
    public static BookingMapper getInstance(){

        if(bookingMapper == null){
            bookingMapper = new BookingMapper();
        }

        return bookingMapper;

    }


//Es folgen nun alle methoden, die die Tabelle booking verändern können, bzw. deren inhalte abrufen können


    /* Ein Booking in die Datenbank einfügen.
     * @param das Booking Objekt welches hinzugefügt werden soll, die dazugehörende PassengerID und die flightRealizationID. Die Attribute seatPosition und das Check in Date wird hier NICHT eingefügt.
     * Das Einfügen dieser Attribute erfolgt in der Methode executeCheckInForBooking
     * @return das eingefügte Objekt.
     * Diese Methode wird den Primärschlüssel automatisch erzeugt. Der größte vorhandene Schlüssel wird um 1 erhöht.
     */
    public Booking insert (Booking b){
        //DB verbindung vom Connection Manager Objekt holen
        Connection con = this.manager.getConnection();

        try{
            // Leeres SQL-Statement (JDBC) anlegen
            Statement stmt = con.createStatement();

            /*
             * Zunächst schauen wir nach, welches der momentan größte
             * Primärschlüsselwert einer Booking ist.
             */
            ResultSet maxId = stmt.executeQuery("SELECT MAX(bookingId) AS maxId " +"FROM booking");

            //die ergebnis Tabelle muss eine maxId zurückgeben.
            if(maxId.next()){
                try{

                 //Das einzufügende Objekt a erhält den neu errechneten Primärschlüssel
                 b.setBookingId(maxId.getInt("maxId") + 1);

                    stmt = con.createStatement();

                     /**
                     * Jetzt erst erfolgt die tatsächliche Einfügeoperation.
                     * Die Attribute der Booking Tabelle werden mit den attributen des booking Objekts gefüllt.
                     */
                    stmt.executeUpdate("INSERT INTO booking (bookingId, passengerId, realizationId) "+
                            "VALUES (" + "'"+
                            b.getBookingId()+"'"+", "+"'"+
                            b.getPassengerId()+"'"+", "+"'"+
                            b.getRealizationId()+"'"+")");
                }
                catch(RemoteException ex){
                    ex.printStackTrace();
                    return null;
                }
            }

        }
        //falls die sql abfrage fehlschlägt...
        catch (SQLException e2) {
            e2.printStackTrace();
            return null;
        }
        //dieses return ist notwendig, da sich die ID der Booking im Laufe der Methode verändert und deswegen das ganze Objekt wieder zurückgegeben wird.
        return b;
    }







    /* Eine Booking updaten, d.h. die seatPsoition, die passengerId und die realizationId kann geändert werden.
     * Es ist zu beachten, falls die realizationId geändert wird, muss der Platz für diese Realization wieder frei gegeben werden. Dieses Logik muss in der Verwaltung implementiert sein.
     * Die Attribute seatPosition und das Check in Date wird hier NICHT aktualisiert.
     * Das Aktualisieren bzw. Einfügen dieser Attribute erfolgt in der Methode executeCheckInForBooking
     * @param das Booking Objekt.
     */
     public void update (Booking b){

         //DB verbindung vom Connection Manager Objekt holen
        Connection con = this.manager.getConnection();

        try{
                //sql statement
            PreparedStatement stmt = con.prepareStatement("UPDATE booking "+
                    "SET passengerId= "+"'"+b.getPassengerId()+"'"+", "+
                    "realizationId= "+"'"+b.getRealizationId()+"'"+
                    " WHERE bookingId = "+"'"+b.getBookingId()+"'");
            //dieser integer beinhaltet die anzahl der veränderten datensätze nach einer bestimmten UPDATE operation
            int anzahlVeraenderterDatensaetze = stmt.executeUpdate();
            }
            //falls der Zugriff auf die Klasse Booking scheitert
            catch(RemoteException ex){
                ex.printStackTrace();
            }

        //falls die sql abfrage fehlschlägt...
        catch (SQLException e2) {
            e2.printStackTrace();
        }

     }


     /*Eine bestimmte Booking in der Datenbank löschen
      * @param die zu löschendes Booking
      */
     public void delete (Booking b){

        //DB-Verbindung vom Connection Manager holen
        Connection con = this.manager.getConnection();

        try {
            // Leeres SQL-Statement anlegen
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM booking "+
                               "WHERE bookingId = "+"'"+b.getBookingId()+"'");
        }
        //falls der Zugriff auf die Klasse Booking fehlschlägt
        catch (RemoteException ex){
            ex.printStackTrace();
        }
        //falls der sql Befehl fehlschlägt
        catch (SQLException e2) {
            e2.printStackTrace();
        }

     }
     
     /*Alle Bookings, die eine spezielle FlightRealization haben löschen
      * @param die flightRealization ID
      */
     public void deleteAllBookingsAssociatedWithFlightRId (int realizationId){

        //DB-Verbindung vom Connection Manager holen
        Connection con = this.manager.getConnection();

        try {
            // Leeres SQL-Statement anlegen
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM booking "+
                               "WHERE realizationId = "+"'"+realizationId+"'");
        }

        //falls der sql Befehl fehlschlägt
        catch (SQLException e2) {
            e2.printStackTrace();
        }

     }





     /*Alle Bookings eines bestimmten Passengers löschen
      * @param die passengerId
      */
     public void deleteAllBookingsFromPassenger (int passengerId){

        //DB-Verbindung vom Connection Manager holen
        Connection con = this.manager.getConnection();

        try {
            // Leeres SQL-Statement anlegen
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM booking "+
                               "WHERE passengerId = "+"'"+passengerId+"'");
        }
        //falls der sql Befehl fehlschlägt
        catch (SQLException e2) {
            e2.printStackTrace();
        }

     }




     /*Alle Bookings, die in der Tabelle vorhanden sind werden zurückgegeben
      *
      *@return Vector mit allen Bookings
      */
     public Vector<Booking> findAll(){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();
         //Vector, der alle Booking Objekte festhalten wird, die in der Tabelle booking stehen
         Vector<Booking> allBookings = new Vector<Booking>();

         try{

             Statement stmt = con.createStatement();
             //das ergebnis der abfrage in ein ResultSet "Tabelle" abspeichern. D.h. jedes Tupel wird in eine Zeile des resultSets abgespeichert
             ResultSet allBookingsQueryResult = stmt.executeQuery("SELECT bookingId, checkInDate, seatPosition, passengerId, realizationId FROM booking "+"ORDER BY bookingId");

             //solange die ergebnisTabelle eine nachfolgende Zeile(Datensatz) hat, wird ein neues Aircraft Objekt erstellt und zum ergebnisVector hinzugefügt.
             while(allBookingsQueryResult.next()){
                 //ein neues Booking Objekt anlegen, welches in den ergebnisvektor aufgenommen wird
                 Booking b = new BookingImpl(allBookingsQueryResult.getInt("passengerId"), allBookingsQueryResult.getInt("realizationId"));

                 //alle anderen Attribute setzen die nicht über den konstruktor gesetzt werden können.
                 b.setBookingId(allBookingsQueryResult.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(allBookingsQueryResult.getTimestamp("checkInDate")));
                 b.setSeatPosition(allBookingsQueryResult.getString("seatPosition"));

                 //das gerade erstellte Objekt wird zum Ergebnisvektor hinzugefügt
                 allBookings.addElement(b);
             }

         }
         catch(RemoteException ex){
             ex.printStackTrace();
         }
         catch(SQLException sqlE){
             sqlE.printStackTrace();
         }
         //der vector mit allen bookings aus der Tabelle wird zurückgegeben
         return allBookings;
     }



     /*Alle Bookings, die in der Tabelle vorhanden sind und bei denen der Passagier schon eingecheckt hat, werden zurückgegeben
      *
      *@return Vector mit allen Bookings
      */
     public Vector<Booking> findAllByAlreadyCheckedIn(){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();
         //Vector, der alle Booking Objekte festhalten wird, die in der Tabelle booking stehen
         Vector<Booking> allBookings = new Vector<Booking>();

         try{

             Statement stmt = con.createStatement();
             //das ergebnis der abfrage in ein ResultSet "Tabelle" abspeichern. D.h. jedes Tupel wird in eine Zeile des resultSets abgespeichert
             ResultSet allBookingsQueryResult = stmt.executeQuery("SELECT bookingId, checkInDate, seatPosition, passengerId, realizationId FROM booking "+"WHERE NOT seatPosition = '' "+"ORDER BY bookingId");

             //solange die ergebnisTabelle eine nachfolgende Zeile(Datensatz) hat, wird ein neues Aircraft Objekt erstellt und zum ergebnisVector hinzugefügt.
             while(allBookingsQueryResult.next()){
                 //ein neues Booking Objekt anlegen, welches in den ergebnisvektor aufgenommen wird
                 Booking b = new BookingImpl(allBookingsQueryResult.getInt("passengerId"), allBookingsQueryResult.getInt("realizationId"));

                 //alle anderen Attribute setzen die nicht über den konstruktor gesetzt werden können.
                 b.setBookingId(allBookingsQueryResult.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(allBookingsQueryResult.getTimestamp("checkInDate")));
                 b.setSeatPosition(allBookingsQueryResult.getString("seatPosition"));

                 //das gerade erstellte Objekt wird zum Ergebnisvektor hinzugefügt
                 allBookings.addElement(b);
             }

         }
         catch(RemoteException ex){
             ex.printStackTrace();
         }
         catch(SQLException sqlE){
             sqlE.printStackTrace();
         }
         //der vector mit allen bookings aus der Tabelle wird zurückgegeben
         return allBookings;
     }

          /*Alle Bookings, die in der Tabelle vorhanden sind und bei denen der Passagier schon eingecheckt hat, werden zurückgegeben
      *
      *@return Vector mit allen Bookings
      */
     public Vector<Booking> findAllByAlreadyCheckedInAndSpecificFlightRealization(int realizationId){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();
         //Vector, der alle Booking Objekte festhalten wird, die in der Tabelle booking stehen
         Vector<Booking> allBookings = new Vector<Booking>();

         try{

             Statement stmt = con.createStatement();
             //das ergebnis der abfrage in ein ResultSet "Tabelle" abspeichern. D.h. jedes Tupel wird in eine Zeile des resultSets abgespeichert
             ResultSet allBookingsQueryResult = stmt.executeQuery("SELECT bookingId, checkInDate, seatPosition, passengerId, realizationId FROM booking "+"WHERE NOT seatPosition = '' "+
                                                                  "AND realizationId = "+"'"+realizationId+"'"+"ORDER BY bookingId");

             //solange die ergebnisTabelle eine nachfolgende Zeile(Datensatz) hat, wird ein neues Aircraft Objekt erstellt und zum ergebnisVector hinzugefügt.
             while(allBookingsQueryResult.next()){
                 //ein neues Booking Objekt anlegen, welches in den ergebnisvektor aufgenommen wird
                 Booking b = new BookingImpl(allBookingsQueryResult.getInt("passengerId"), allBookingsQueryResult.getInt("realizationId"));

                 //alle anderen Attribute setzen die nicht über den konstruktor gesetzt werden können.
                 b.setBookingId(allBookingsQueryResult.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(allBookingsQueryResult.getTimestamp("checkInDate")));
                 b.setSeatPosition(allBookingsQueryResult.getString("seatPosition"));

                 //das gerade erstellte Objekt wird zum Ergebnisvektor hinzugefügt
                 allBookings.addElement(b);
             }

         }
         catch(RemoteException ex){
             ex.printStackTrace();
         }
         catch(SQLException sqlE){
             sqlE.printStackTrace();
         }
         //der vector mit allen bookings aus der Tabelle wird zurückgegeben
         return allBookings;
     }




     /*Eine bestimmte Booking abhängig von der ID finden
      *
      * @param die BookingID als integer
      * @return das gesuchte Booking Objekt
      */

     public Booking findById(int bookingId){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();

         try{

             Statement stmt = con.createStatement();

             ResultSet desiredBooking = stmt.executeQuery("SELECT * FROM booking "+
                                                           "WHERE bookingId = "+"'"+bookingId+"'");

             //es gibt nur eine Booking mit gleicher ID. Es wird zunächst geschaut ob, ein Booking in der ResultSet "Tabelle" ist
             if(desiredBooking.next()){
                 //den ergebnisDatensatz in ein Objekt umwandeln
                 Booking b = new BookingImpl(desiredBooking.getInt("passengerId"), desiredBooking.getInt("realizationId"));
                 b.setBookingId(desiredBooking.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(desiredBooking.getTimestamp("checkInDate")));
                 b.setSeatPosition(desiredBooking.getString("seatPosition"));
                 //das gefundene booking Objekt zurückgeben
                 return b;
             }

         }
         //falls der Zugriff auf die Klasse booking fehlschlägt
        catch (RemoteException ex){
            ex.printStackTrace();
            return null;
        }
        //falls der sql Befehl fehlschlägt
        catch (SQLException e2) {
            e2.printStackTrace();
            return null;
        }
        //wenn kein booking gefunden wurde und keine fehlermeldung ausgegeben wurde, gibt die Methode null zurück.
         return null;
     }


     /*Eine bestimmte Booking abhängig von der PassgengerID finden
      *
      * @param die PassengerID als integer
      * @return ein Vector mit allen zutreffenden Booking objekten
      */

     public Vector<Booking> findAllByPassengerId(int passengerId){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();
         //Vector, der alle Booking Objekte festhalten wird, die in der Tabelle booking stehen
         Vector<Booking> allBookings = new Vector<Booking>();

         try{

             Statement stmt = con.createStatement();
             //das ergebnis der abfrage in ein ResultSet "Tabelle" abspeichern. D.h. jedes Tupel wird in eine Zeile des resultSets abgespeichert
             ResultSet allBookingsQueryResult = stmt.executeQuery("SELECT * FROM booking "+
                                                           "WHERE passengerId = "+"'"+passengerId+"'");

             //solange die ergebnisTabelle eine nachfolgende Zeile(Datensatz) hat, wird ein neues Aircraft Objekt erstellt und zum ergebnisVector hinzugefügt.
             while(allBookingsQueryResult.next()){
                 //ein neues Booking Objekt anlegen, welches in den ergebnisvektor aufgenommen wird
                 Booking b = new BookingImpl(allBookingsQueryResult.getInt("passengerId"), allBookingsQueryResult.getInt("realizationId"));

                 //alle anderen Attribute setzen die nicht über den konstruktor gesetzt werden können.
                 b.setBookingId(allBookingsQueryResult.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(allBookingsQueryResult.getTimestamp("checkInDate")));
                 b.setSeatPosition(allBookingsQueryResult.getString("seatPosition"));

                 //das gerade erstellte Objekt wird zum Ergebnisvektor hinzugefügt
                 allBookings.addElement(b);
             }

         }
         catch(RemoteException ex){
             ex.printStackTrace();
         }
         catch(SQLException sqlE){
             sqlE.printStackTrace();
         }
         //der vector mit allen bookings aus der Tabelle wird zurückgegeben
         return allBookings;
     }


     /*Eine bestimmte Booking abhängig von der PassgengerID und der RealizationID finden
      *
      * @param die realizationI und PassengerID als integer
      * @return ein Vector mit allen zutreffenden Booking objekten
      */

     public Vector<Booking> findAllByRealizationIdAndPassengerId(int realizationId, int passengerId){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();
         //Vector, der alle Booking Objekte festhalten wird, die in der Tabelle booking stehen
         Vector<Booking> allBookings = new Vector<Booking>();

         try{

             Statement stmt = con.createStatement();
             //das ergebnis der abfrage in ein ResultSet "Tabelle" abspeichern. D.h. jedes Tupel wird in eine Zeile des resultSets abgespeichert
             ResultSet allBookingsQueryResult = stmt.executeQuery("SELECT * FROM booking "+
                                                           "WHERE realizationId = "+"'"+realizationId+"'"+
                                                           "AND passengerId = "+"'"+passengerId+"'");

             //solange die ergebnisTabelle eine nachfolgende Zeile(Datensatz) hat, wird ein neues Aircraft Objekt erstellt und zum ergebnisVector hinzugefügt.
             while(allBookingsQueryResult.next()){
                 //ein neues Booking Objekt anlegen, welches in den ergebnisvektor aufgenommen wird
                 Booking b = new BookingImpl(allBookingsQueryResult.getInt("passengerId"), allBookingsQueryResult.getInt("realizationId"));

                 //alle anderen Attribute setzen die nicht über den konstruktor gesetzt werden können.
                 b.setBookingId(allBookingsQueryResult.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(allBookingsQueryResult.getTimestamp("checkInDate")));
                 b.setSeatPosition(allBookingsQueryResult.getString("seatPosition"));

                 //das gerade erstellte Objekt wird zum Ergebnisvektor hinzugefügt
                 allBookings.addElement(b);
             }

         }
         catch(RemoteException ex){
             ex.printStackTrace();
         }
         catch(SQLException sqlE){
             sqlE.printStackTrace();
         }
         //der vector mit allen bookings aus der Tabelle wird zurückgegeben
         return allBookings;
     }

     /*Eine bestimmte Booking abhängig von der PassgengerID und der RealizationID finden
      *
      * @param die realizationI und PassengerID als integer
      * @return ein Vector mit allen zutreffenden Booking objekten
      */

     public Vector<Booking> findAllByRealizationId(int realizationId){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();
         //Vector, der alle Booking Objekte festhalten wird, die in der Tabelle booking stehen
         Vector<Booking> allBookings = new Vector<Booking>();

         try{

             Statement stmt = con.createStatement();
             //das ergebnis der abfrage in ein ResultSet "Tabelle" abspeichern. D.h. jedes Tupel wird in eine Zeile des resultSets abgespeichert
             ResultSet allBookingsQueryResult = stmt.executeQuery("SELECT * FROM booking "+
                                                           "WHERE realizationId = "+"'"+realizationId+"'");

             //solange die ergebnisTabelle eine nachfolgende Zeile(Datensatz) hat, wird ein neues Aircraft Objekt erstellt und zum ergebnisVector hinzugefügt.
             while(allBookingsQueryResult.next()){
                 //ein neues Booking Objekt anlegen, welches in den ergebnisvektor aufgenommen wird
                 Booking b = new BookingImpl(allBookingsQueryResult.getInt("passengerId"), allBookingsQueryResult.getInt("realizationId"));

                 //alle anderen Attribute setzen die nicht über den konstruktor gesetzt werden können.
                 b.setBookingId(allBookingsQueryResult.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(allBookingsQueryResult.getTimestamp("checkInDate")));
                 b.setSeatPosition(allBookingsQueryResult.getString("seatPosition"));

                 //das gerade erstellte Objekt wird zum Ergebnisvektor hinzugefügt
                 allBookings.addElement(b);
             }

         }
         catch(RemoteException ex){
             ex.printStackTrace();
         }
         catch(SQLException sqlE){
             sqlE.printStackTrace();
         }
         //der vector mit allen bookings aus der Tabelle wird zurückgegeben
         return allBookings;
     }


     /*Sie erste Booking abhängig von der realizationID finden
      *
      * @param die realizationID als integer
      * @return das gesuchte Booking Objekt
      */

     public Booking findByRealizationId(int realizationId){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();

         try{

             Statement stmt = con.createStatement();

             ResultSet desiredBooking = stmt.executeQuery("SELECT * FROM booking "+
                                                           "WHERE bookingId = "+"'"+realizationId+"'");

             //es gibt nur eine Booking mit gleicher ID. Es wird zunächst geschaut ob, ein Booking in der ResultSet "Tabelle" ist
             if(desiredBooking.next()){
                 //den ergebnisDatensatz in ein Objekt umwandeln
                 Booking b = new BookingImpl(desiredBooking.getInt("passengerId"), desiredBooking.getInt("realizationId"));
                 b.setBookingId(desiredBooking.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(desiredBooking.getTimestamp("checkInDate")));
                 b.setSeatPosition(desiredBooking.getString("seatPosition"));
                 //das gefundene booking Objekt zurückgeben
                 return b;
             }

         }
         //falls der Zugriff auf die Klasse booking fehlschlägt
        catch (RemoteException ex){
            ex.printStackTrace();
            return null;
        }
        //falls der sql Befehl fehlschlägt
        catch (SQLException e2) {
            e2.printStackTrace();
            return null;
        }
        //wenn kein booking gefunden wurde und keine fehlermeldung ausgegeben wurde, gibt die Methode null zurück.
         return null;
     }


     /*Einen Check in für eine bestimmte Booking durchführen
      *
      * @param das booking Objekt
      * @return boolean
      */

     public boolean executeCheckInForSpecificBooking (Booking b){
        //DB verbindung vom Connection Manager Objekt holen
        Connection con = this.manager.getConnection();

        

        try{

            //das DateObjekt aus dem booking Objekt in einen sql timestamp umwandeln
            Timestamp checkInDate = dateToSqlTimestamp(b.getCheckInDate());


                //sql statement
            PreparedStatement stmt = con.prepareStatement("UPDATE booking "+
                    "SET checkInDate= "+"'"+checkInDate+"'"+", "+
                    "seatPosition= "+"'"+b.getSeatPosition()+"'"+
                    " WHERE bookingId = "+"'"+b.getBookingId()+"'");
            //dieser integer beinhaltet die anzahl der veränderten datensätze nach einer bestimmten UPDATE operation
            int anzahlVeraenderterDatensaetze = stmt.executeUpdate();

            return true;
            }
            //falls der Zugriff auf die Klasse Booking scheitert
            catch(RemoteException ex){
                ex.printStackTrace();
            }

        //falls die sql abfrage fehlschlägt...
        catch (SQLException e2) {
            e2.printStackTrace();
        }
        //wenn der update fehlschlägt, wird false zurück gegeben
        return false;
     }





     /*Prüfen, ob ein Passagier einer bestimmten Buchung schon eingechekt hat.
      *
      * @param die bookingId
      * @return true == ja, eingechekt   false == nein, nicht eingecheckt
      */

     public boolean verifyCheckInStatusOfBooking(int bookingId){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();

         try{

             Statement stmt = con.createStatement();

             ResultSet desiredBooking = stmt.executeQuery("SELECT * FROM booking "+
                                                           "WHERE bookingId = "+"'"+bookingId+"'");

             //es gibt nur eine Booking mit gleicher ID. Es wird zunächst geschaut ob, ein Booking in der ResultSet "Tabelle" ist
             if(desiredBooking.next()){
                 //den ergebnisDatensatz in ein Objekt umwandeln
                 Booking b = new BookingImpl(desiredBooking.getInt("passengerId"), desiredBooking.getInt("realizationId"));
                 b.setBookingId(desiredBooking.getInt("bookingId"));
                 b.setCheckInDate(sqlTimestampToDate(desiredBooking.getTimestamp("checkInDate")));
                 b.setSeatPosition(desiredBooking.getString("seatPosition"));

                 /*das gefundene booking Objekt überprüfen, ob schon eingecheckt wurde oder nicht.
                  *Sollte das Attribut ungleich 1970-01-01 ist, wird true zurück gegeben, denn das stellt sicher das eingecheckt wurde.
                  */
                 if(!(b.getCheckInDate().toString()).equals("Thu Jan 01 01:00:00 CET 1970")){
                     //ja eingecheckt
                     return true;
                 }

             }

         }
         //falls der Zugriff auf die Klasse booking fehlschlägt
        catch (RemoteException ex){
            ex.printStackTrace();

        }
        //falls der sql Befehl fehlschlägt
        catch (SQLException e2) {
            e2.printStackTrace();

        }
        //wenn der passagier noch nicht eingecheckt hat, wird false zurück gegeben
         return false;
     }


     /*Alle Bookings, die für eine bestimmte FlightRealization vorhanden sind.
      * Diese Methode wird benötigt, um zu erfahren, ob noch Plätze für die angegebene FlugRealization frei sind.
      * Wenn die Methode -1 zurück gibt, ist ein Fehler aufgetreten
      *@return Anzahl der existierenden Buchungen für diese Realization
      */
     public int findNumberOfBookingsForRealizationId(int realizationId){

         //DB-Verbindung vom Connection Manager holen
         Connection con = this.manager.getConnection();


         try{

             Statement stmt = con.createStatement();
              // 1. Abfrage: Anzahl Zeilen ermitteln
              ResultSet anzahl = stmt.executeQuery("SELECT COUNT(*) FROM booking "+
                                                           "WHERE realizationId = "+"'"+realizationId+"'");

              anzahl.next();
              int anzahlVerfuegbarerBuchungen = anzahl.getInt(1);

            return anzahlVerfuegbarerBuchungen;
             }

         catch(SQLException sqlE){
             sqlE.printStackTrace();
         }

         return -1;
     }
















    //helfer Methode für die Umwandlung von Sql Timestamp in java.util.Date
    //Quelle: http://blog.mynotiz.de/programmieren/mysql-timestamp-in-java-date-umwandeln-und-umgekehrt-285/
    public Date sqlTimestampToDate(Timestamp timestamp){
        
         if(timestamp == null){
             Timestamp nullWerte = new Timestamp(0);
             Date dateNullWerte = new Date(nullWerte.getTime());
             return dateNullWerte;
         }
        else{
            Date date = new Date(timestamp.getTime());
            return date;
         }
  }


    //helfer Methode für die Umwandlung von java.util.Date in Timestamp sql
    //Quelle: http://blog.mynotiz.de/programmieren/mysql-timestamp-in-java-date-umwandeln-und-umgekehrt-285/
    public Timestamp dateToSqlTimestamp(Date date){

        Timestamp timestamp = new Timestamp(date.getTime());
        return timestamp;
  }




}


